package cn.siriusbot.rpc.server;

import cn.siriusbot.rpc.SiriusBotRpcServer;
import cn.siriusbot.rpc.SiriusLogger;
import cn.siriusbot.rpc.entity.RpcBody;
import cn.siriusbot.rpc.entity.RpcError;
import cn.siriusbot.siriuspro.error.MsgException;
import cn.siriusbot.siriuspro.web.R.R;
import cn.siriusbot.siriuspro.web.pojo.BotHttpRequest;
import com.alibaba.fastjson2.JSONObject;

import java.util.UUID;

/**
 * 基于Http连接的rpc服务端
 */
public class HttpSiriusBotRpcServer extends BasicsSiriusBotRpcServer implements SiriusBotRpcServer {

    public HttpSiriusBotRpcServer() {
    }

    public HttpSiriusBotRpcServer(SiriusLogger log) {
        super(log);
    }

    /**
     * 解析一个http请求
     *
     * @param request http请求body
     */
    public R parsecBotHttpRequest(BotHttpRequest request) {
        RpcBody rpcBody;
        try {
            rpcBody = JSONObject.parseObject(request.getBody(), RpcBody.class);
            if (rpcBody.getId() == null) return new R().setCode(500).setMsg("ID为空");
            if (rpcBody.getApi() == null) return new R().setCode(500).setMsg("API为空");
            if (rpcBody.getMethod() == null) return new R().setCode(500).setMsg("Method为空");
        } catch (Throwable ignored) {
            return new R().setCode(500).setMsg("序列化请求失败!");
        }
        // 序列化成功，开始处理
        RpcBody resultBody = new RpcBody().setId(rpcBody.getId());
        try {
            final Object result = getResult(rpcBody);
            // 发送正常结果
            resultBody.setResult(result);

        } catch (Throwable e) {
            Throwable item = e;
            while (!(item instanceof MsgException) && item.getCause() != null) {
                item = item.getCause();
            }
            final RpcError rpcError = new RpcError().setErrorId(UUID.randomUUID().toString());
            rpcError.setMessage(item.getMessage());
            log.error(String.format("程序调用错误，错误标记码：%s%n", rpcError.getErrorId()), e);
            resultBody.setError(rpcError);
        }
        return new R()
                .setCode(0)
                .setData(resultBody);
    }

}
